Metabox & metadata
SkillDo CMS sở hữu tính năng Metabox mạnh mẽ giúp bạn thêm "Bảng Phụ" để lưu thêm nhiều thông tin dưới dạng Metadata mà KHÔNG CẦN đụng đến Cột (Column) trong Bảng Chính!
1. Hoạt Động (Hook)
SkillDo quy định 2 Action chính để bạn thao tác với giao diện tạo/sửa Bài Viết (hoặc Chủ Đề, Category):
add_meta_box: Action yêu cầu in một vùng HTML Form nằm lọt thỏm trong giao diện chung.save_{module}_object: Action gọi khi người quản trị Lưu Cập Nhật (cả thêm mới lẫn cập nhật), nhận tham số($id, $request, $insertData, $dataOutside). Ngoài ra còn có:save_{module}_object_add– chỉ khi thêm mớisave_{module}_object_edit– chỉ khi cập nhậtsave_object– bắt tất cả module, nhận thêm$moduleở tham số thứ 2
Bộ thư viện Form Builder (Mảng Array giống Plugin Element) được sử dụng để sinh ra giao diện TextBox / Select / Radio cho Metadata một cách đồng bộ nhất với Admin thay vì bạn phải tự cặm cụi code tay HTML Bootstrap.
2. Nơi Đăng Ký Metabox Trong Theme
Cách tổ chức chuẩn trong theme là:
- Tạo một class riêng ở
theme-child/app/Custom/để đóng gói toàn bộ logic đăng ký + render + lưu. - Đăng ký class vào hệ thống tại
theme-child/bootstrap/theme-child.phpbằngadd_action.
3. Bước 1 – Tạo Class Metabox trong theme-child/app/Custom/
Tạo file theme-child/app/Custom/PostSourceMetabox.php:
<?php
namespace Theme\Custom;
use SkillDo\Cms\Metabox\Metabox;
use SkillDo\Cms\Form\Form;
use SkillDo\Http\Request;
use Metadata;
class PostSourceMetabox
{
/**
* Đăng ký metabox vào hệ thống.
* Được gọi qua add_action('add_meta_box', ...) từ bootstrap.
*/
public static function register(): void
{
// Metabox::add($id, $title, $callback, $args = [])
Metabox::add(
'source_post_metabox', // ID Bảng Phụ
'Nguồn Gốc Của Bài Viết Này', // Tiêu đề của Box
[static::class, 'render'], // Hàm callback render form
[
'module' => 'post', // Áp dụng cho module (post, page, products...)
'position' => 10, // Thứ tự sắp xếp hiển thị
'content' => 'leftBottom' // Vị trí (leftBottom | leftTop | right)
]
);
}
/**
* Render nội dung Form trong Box.
* Hệ thống tự truyền $object là Post Data (khi Sửa) hoặc null (khi Thêm mới).
*/
public static function render($object): void
{
// Lấy Metadata đã lưu cũ từ DB (Nếu đang ở trang Sửa). Còn Thêm mới sẽ rỗng = ''
$source_name = Metadata::get('post', $object->id, '_source_name', '');
$source_url = Metadata::get('post', $object->id, '_source_url', '');
// Sử dụng SkillDo Form Builder để in HTML chuẩn
$form = new Form();
echo $form->text('source_name', [
'label' => 'Tên Tạp chí/Báo gốc',
'value' => $source_name,
'placeholder' => 'VD: VNExpress'
]);
echo $form->url('source_url', [
'label' => 'Đường dẫn link báo gốc',
'value' => $source_url
]);
}
/**
* Lưu dữ liệu khi người dùng nhấn Lưu bài viết.
* Được gọi qua add_action('save_post_object', ...) từ bootstrap.
*
* Hook save thực tế (xem FormAdminHelper):
* - save_{module}_object : cả thêm mới lẫn cập nhật → ($id, $request, $insertData, $dataOutside)
* - save_{module}_object_add : chỉ khi thêm mới
* - save_{module}_object_edit : chỉ khi cập nhật
* - save_object : tất cả module → ($id, $module, $request, $insertData, $dataOutside)
*
* @param int $post_id ID bài viết vừa lưu
* @param Request $request HTTP Request chứa dữ liệu form
* @param array $insertData Dữ liệu đã được insert vào DB
* @param array $dataOutside Dữ liệu nằm ngoài model (meta, file...)
*/
public static function save(int $post_id, Request $request, array $insertData, array $dataOutside): void
{
if ($request->has('source_name')) {
Metadata::update('post', $post_id, '_source_name', $request->input('source_name'));
Metadata::update('post', $post_id, '_source_url', $request->input('source_url'));
}
}
}
4. Bước 2 – Đăng Ký vào Hệ Thống tại theme-child/bootstrap/theme-child.php
<?php
use Theme\Custom\PostSourceMetabox;
// Đăng ký metabox (hiển thị form phụ trong trang tạo/sửa bài viết)
add_action('add_meta_box', [PostSourceMetabox::class, 'register']);
// Lắng nghe sự kiện lưu bài viết để lưu metadata (cả thêm mới lẫn cập nhật)
// Hook nhận 4 tham số: $id, $request, $insertData, $dataOutside
add_action('save_post_object', [PostSourceMetabox::class, 'save'], 10, 4);
5. Truy Xuất Metadata Ra Màn Hình Frontend
Trong file View Theme theme-store/views/post-detail.blade.php:
@php
// SkillDo Blade đã bơm tự động Object bài viết là biến $post
$name = Metadata::get('post', $post->id, '_source_name', null);
$url = Metadata::get('post', $post->id, '_source_url', null);
@endphp
@if($name && $url)
<div class="source-credit" style="padding:10px; background:#f0f0f0;">
<p><strong>Bản quyền thuộc về:</strong> <a href="{{ $url }}" target="_blank">{{ $name }}</a></p>
</div>
@endif
TỔNG KẾT
| Bước | File | Việc cần làm |
|---|---|---|
| 1 | theme-child/app/Custom/PostSourceMetabox.php | Tạo class chứa register(), render(), save() |
| 2 | theme-child/bootstrap/theme-child.php | Đăng ký 2 action: add_meta_box và save_post_object |
| 3 | View blade frontend | Dùng Metadata::get() để hiển thị ra giao diện người dùng |
Lưu ý quan trọng:
- Lợi dụng khả năng mở rộng không giới hạn của bảng
MetadataCMS (GồmModule Type,Target ID,Key, vàValue). - Dùng Metabox Hook để mượn chỗ đặt form thu thập liệu mà không phải phá hư form Mặc Định CMS.
- Không làm bốc hơi/phình to Hệ Quản Trị Hệ Cơ Sở Dữ Liệu SQL cốt lõi của bảng chính bằng việc hạn chế dùng chức năng Thêm Cột (Col).
- Phân chia rõ ràng (Tên trường bắt đầu bằng gạch dưới
_là Metabox Ẩn ở UI, không gạch là Custom Field mặc định cho Admin).